﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Twitterizer;
using MooneyTool;
using System.Timers;

namespace TwitterChess
{
	class Tweety
	{
		public delegate void TwitterMessageHandler(object feedback, TweetReceivedEventArgs msg);
		public event TwitterMessageHandler TwitterMessageReceived;

		public bool IsAuthenticated;
		public String AuthenticatedAs;

		private static String ConsumerKey = "4YwNFLiDCn86M9HgPDgJtA";
		private static String ConsumerSecret = "Wj0Ex61wReOoq3D91x2i0dWQaARw45uf8kY9CGbvrY";

		private OAuthTokenResponse RequestToken;
		private OAuthTokens Tokens;

		private Timer UpdateTimer;

		private DateTime StartTime;

		private LinkedList<decimal> ReceivedMessageIds;

		public Tweety()
		{
			this.IsAuthenticated = false;
			ReceivedMessageIds = new LinkedList<decimal>();

			RequestToken = OAuthUtility.GetRequestToken(ConsumerKey, ConsumerSecret, "oob");
			Uri AuthorizationUrl = OAuthUtility.BuildAuthorizationUri(RequestToken.Token);
			System.Diagnostics.Process.Start(AuthorizationUrl.AbsoluteUri);
		}

		private void OnTwitterMessageReceived(object feedback, TweetReceivedEventArgs msg)
		{
			try
			{
				if (TwitterMessageReceived != null)
				{
					TwitterMessageReceived(feedback, msg);
				}
				else
				{
					throw new Exception("No listeners to twitter message.");
				}
			}
			catch (Exception ex)
			{
				Logger.getInstance().Add("Failed to call feedback for received message: " + ex.Message);
			}
		}

		public bool Authenticate(String pin)
		{
			try
			{
				OAuthTokenResponse AccessToken = OAuthUtility.GetAccessToken(ConsumerKey, ConsumerSecret, RequestToken.Token, pin);

				Tokens = new OAuthTokens();
				Tokens.AccessToken = AccessToken.Token;
				Tokens.AccessTokenSecret = AccessToken.TokenSecret;
				Tokens.ConsumerKey = ConsumerKey;
				Tokens.ConsumerSecret = ConsumerSecret;
				this.AuthenticatedAs = AccessToken.ScreenName;

				Logger.getInstance().Add("Succesfully authenticated on Twitter.");

				StartTime = DateTime.Now;

				UpdateTimer = new Timer(15000);
				UpdateTimer.Enabled = true;
				UpdateTimer.Elapsed += new ElapsedEventHandler(ReadMessages);
				UpdateTimer.Start();

				this.IsAuthenticated = true;

				SendStartupMessage();

				return true;
			}
			catch (Exception ex)
			{
				Logger.getInstance().Add("Failed to authenticate on Twitter: " + ex.Message);

				return false;
			}
		}

		private void ReadMessages(object source, ElapsedEventArgs e)
		{
			TwitterResponse<TwitterStatusCollection> Messages = TwitterTimeline.Mentions(Tokens);

			foreach (TwitterStatus Message in Messages.ResponseObject)
			{
				if (
					!ReceivedMessageIds.Contains(Message.Id) && // message already received
					Message.CreatedDate.CompareTo(StartTime) > 0 // message sent before app was authenticated
					)
				{
					ReceivedMessageIds.AddLast(Message.Id);

					// strip @reply from Tweet

					//String Tweet = Message.Text.ToString().Substring(Message.Text.IndexOf(" "));
					String Tweet = Message.Text.ToString().Split(' ')[1];
					OnTwitterMessageReceived(this, new TweetReceivedEventArgs(Tweet, Message.User.ScreenName));
				}
			}
		}

		public void SendMessageDelegate(object feedback, AIMoveMadeArgs args)
		{
			this.SendMessage("@" + args.opponent.twitterUserName + " " + args.message + " (" + DateTime.Now.ToShortTimeString() + ")");
		}

		public bool SendMessage(String Message)
		{
			try
			{
				TwitterResponse<TwitterStatus> TweetResponse = TwitterStatus.Update(Tokens, Message);

				if (TweetResponse.Result == RequestResult.Success)
				{
					return true;
				}
				else
				{
					Logger.getInstance().Add("Failed to send tweet: " + TweetResponse.Result.ToString() + "."); ;

					return false;
				}
			}
			catch (Exception ex)
			{
				Logger.getInstance().Add("Exception when sending tweet: " + ex.Message);

				return false;
			}
		}

		private void SendStartupMessage()
		{
			this.SendMessage(DateTime.Now.ToShortTimeString() + ": Chess Twitter Bot is now running! Send me a @reply with 'start' to play.");
		}

		private void SendShutdownMessage()
		{
			this.SendMessage(DateTime.Now.ToShortTimeString() + ": Chess Twitter Bot is now shutting down.");
		}

		~Tweety()
		{
			if (this.IsAuthenticated)
			{
				this.SendShutdownMessage();
			}
		}
	}
}
